[DMS] MongoDBからRDS MySQLへのレプリケーションを試す
こんにちは、菊池です。
MongoDBからのDMSレプリケーション、S3ターゲットに続きMySQLでも試してみました。これまでの記事は以下を参照ください。
- Database Migration Service の Source に MongoDB が選択可能になりました!
- [DMS] MongoDB Sourceのマイグレーションモードを比較する
- [DMS] MongoDB:テーブルモードのデータパターン検証
検証
SourceとしてEC2で動作するMongoDBのレプリカセット、TargetとしてRDS MySQLインスタンスを利用します。
- Source
- MongoDB 3.4.2
- レプリケーションモード:テーブルモード
- Target
- RDS for MySQL 5.6.27
初期データのマイグレーション
まずはデータを1つMongoDBに挿入し、レプリケーションを実行します。
s0-rs0:PRIMARY> use main switched to db main s0-rs0:PRIMARY> s0-rs0:PRIMARY> db.users.insert( ... { ... userid : 001, ... name : "hoge1", ... joined : ISODate("2017-04-01"), ... likes : [ "tennis", "golf", "swimming" ] ... } ... ); WriteResult({ "nInserted" : 1 }) s0-rs0:PRIMARY> s0-rs0:PRIMARY> db.users.find() { "_id" : ObjectId("5905346cb1ae627be955aca4"), "userid" : 1, "name" : "hoge1", "joined" : ISODate("2017-04-01T00:00:00Z"), "likes" : [ "tennis", "golf", "swimming" ] }
この状態でレプリケーションタスクを実行します。移行先のMySQLでデータベースを確認します。
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | awsdms_control | | innodb | | main | | mysql | | performance_schema | | sys | | test | +--------------------+
main
データベースが作成されています。テーブルも確認してみます。
mysql> show tables from main; +----------------+ | Tables_in_main | +----------------+ | users | +----------------+
users
テーブルが作成されました。レコードを確認します。
mysql> select * from users; +--------------------------+--------+-------+---------------------+----------------------------------+ | $OID:_id | userid | name | joined | $ARRAY:likes | +--------------------------+--------+-------+---------------------+----------------------------------+ | 5905346cb1ae627be955aca4 | 1 | hoge1 | 2017-04-01 00:00:00 | [ "tennis", "golf", "swimming" ] | +--------------------------+--------+-------+---------------------+----------------------------------+ 1 row in set (0.00 sec)
レプリケーションが実行されました。配列の列は$ARRAY
で定義されています。
CDCの実行
続けてMongoDBにデータを追加して、CDCが実行されることを確認します。
s0-rs0:PRIMARY> db.users.insert( ... { ... userid : 002, ... name : "hoge2", ... joined : ISODate("2017-04-01"), ... } ... ); WriteResult({ "nInserted" : 1 }) s0-rs0:PRIMARY> db.users.find() { "_id" : ObjectId("5905346cb1ae627be955aca4"), "userid" : 1, "name" : "hoge1", "joined" : ISODate("2017-04-01T00:00:00Z"), "likes" : [ "tennis", "golf", "swimming" ] } { "_id" : ObjectId("59053611b1ae627be955aca5"), "userid" : 2, "name" : "hoge2", "joined" : ISODate("2017-04-01T00:00:00Z") } s0-rs0:PRIMARY>
MySQLのデータを確認します。
mysql> select * from users; +--------------------------+--------+-------+---------------------+----------------------------------+ | $OID:_id | userid | name | joined | $ARRAY:likes | +--------------------------+--------+-------+---------------------+----------------------------------+ | 5905346cb1ae627be955aca4 | 1 | hoge1 | 2017-04-01 00:00:00 | [ "tennis", "golf", "swimming" ] | | 59053611b1ae627be955aca5 | 2 | hoge2 | 2017-04-01 00:00:00 | NULL | +--------------------------+--------+-------+---------------------+----------------------------------+ 2 rows in set (0.00 sec)
データが同期されています。挿入したデータになかった項目はNULL
となっています。
次に、型が異なるデータを挿入してみます。joind
を文字列で挿入します。
s0-rs0:PRIMARY> db.users.insert( ... { ... userid : 003, ... name : "hoge3", ... joined : "2017-04-01", ... likes : [ "tennis" ] ... } ... ); WriteResult({ "nInserted" : 1 }) s0-rs0:PRIMARY> db.users.find() { "_id" : ObjectId("5905346cb1ae627be955aca4"), "userid" : 1, "name" : "hoge1", "joined" : ISODate("2017-04-01T00:00:00Z"), "likes" : [ "tennis", "golf", "swimming" ] } { "_id" : ObjectId("59053611b1ae627be955aca5"), "userid" : 2, "name" : "hoge2", "joined" : ISODate("2017-04-01T00:00:00Z") } { "_id" : ObjectId("59053671b1ae627be955aca6"), "userid" : 3, "name" : "hoge3", "joined" : "2017-04-01", "likes" : [ "tennis" ] } s0-rs0:PRIMARY>
MySQL側では型が異なるとNULL
となっています。
mysql> select * from users; +--------------------------+--------+-------+---------------------+----------------------------------+ | $OID:_id | userid | name | joined | $ARRAY:likes | +--------------------------+--------+-------+---------------------+----------------------------------+ | 5905346cb1ae627be955aca4 | 1 | hoge1 | 2017-04-01 00:00:00 | [ "tennis", "golf", "swimming" ] | | 59053611b1ae627be955aca5 | 2 | hoge2 | 2017-04-01 00:00:00 | NULL | | 59053671b1ae627be955aca6 | 3 | hoge3 | NULL | [ "tennis" ] | +--------------------------+--------+-------+---------------------+----------------------------------+ 3 rows in set (0.00 sec)
先ほどのデータを更新して、正しいデータ型にupdateします。
s0-rs0:PRIMARY> db.users.updateOne( ... { userid : 003 }, ... { $set: { joined : ISODate("2017-04-01") } } ... ); { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
更新が反映されています。
mysql> select * from users; +--------------------------+--------+-------+---------------------+----------------------------------+ | $OID:_id | userid | name | joined | $ARRAY:likes | +--------------------------+--------+-------+---------------------+----------------------------------+ | 5905346cb1ae627be955aca4 | 1 | hoge1 | 2017-04-01 00:00:00 | [ "tennis", "golf", "swimming" ] | | 59053611b1ae627be955aca5 | 2 | hoge2 | 2017-04-01 00:00:00 | NULL | | 59053671b1ae627be955aca6 | 3 | hoge3 | 2017-04-01 00:00:00 | [ "tennis" ] | +--------------------------+--------+-------+---------------------+----------------------------------+ 3 rows in set (0.00 sec)
削除も試してみました。
s0-rs0:PRIMARY> db.users.deleteOne( ... { userid : 003 } ... ); { "acknowledged" : true, "deletedCount" : 1 } s0-rs0:PRIMARY> db.users.find() { "_id" : ObjectId("5905346cb1ae627be955aca4"), "userid" : 1, "name" : "hoge1", "joined" : ISODate("2017-04-01T00:00:00Z"), "likes" : [ "tennis", "golf", "swimming" ] } { "_id" : ObjectId("59053611b1ae627be955aca5"), "userid" : 2, "name" : "hoge2", "joined" : ISODate("2017-04-01T00:00:00Z") } s0-rs0:PRIMARY>
削除もちゃんと同期されました。
mysql> select * from users; +--------------------------+--------+-------+---------------------+----------------------------------+ | $OID:_id | userid | name | joined | $ARRAY:likes | +--------------------------+--------+-------+---------------------+----------------------------------+ | 5905346cb1ae627be955aca4 | 1 | hoge1 | 2017-04-01 00:00:00 | [ "tennis", "golf", "swimming" ] | | 59053611b1ae627be955aca5 | 2 | hoge2 | 2017-04-01 00:00:00 | NULL | +--------------------------+--------+-------+---------------------+----------------------------------+ 2 rows in set (0.00 sec)
まとめ
MongoDBからMySQLへのデータレプリケーションを試しました。
データモデルが異なるデータベースに対しても、一部制約はありつつも継続的なレプリケーションが可能です。移行だけでなく、フロント、非同期な集計、分析用途など、目的に応じて適切なデータベースを使っていくことも可能になります。